home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 26 / Cream of the Crop 26.iso / program / wsc4c21.zip / ANSI.C < prev    next >
C/C++ Source or Header  |  1997-05-22  |  7KB  |  300 lines

  1. /*
  2. **  ansi.c
  3. **
  4. **  ANSI terminal emulator
  5. **
  6. **  Interprets ANSI escape sequences. Think of the keyboard
  7. **  and terminal as an external device and ANSI.C as its
  8. **  interface.
  9. **
  10. **  This module uses PAINT.C as its interface to the actual
  11. **  screen.
  12. **
  13. **  FEATURE             SUPPORTED
  14. **  =======             =========
  15. **  Cursor positioning  Yes
  16. **  Underlining         No
  17. **  Blinking, inverse   No
  18. **  Color               No
  19. **
  20. */
  21.  
  22. #include "windows.h"
  23. #include "paint.h"
  24. #include "ascii.h"
  25. #include "wsc.h"
  26.  
  27. extern HWND hMainWnd;
  28.  
  29. #define SIZE 40
  30.  
  31. static int  Initialized = 0;
  32. static int  Debug = 0;
  33. static int  SavedRow = 0;
  34. static int  SavedCol = 0;
  35. static char ReportBuffer[SIZE];
  36. static int  ReportLeft = 0;
  37. static int  ReportRight = 0;
  38. static char ListBuf[SIZE];      /* escape sequence buffer */
  39. static int  ListCnt  = 0;       /* # characters in ListBuf[] */
  40.  
  41. static char EscSequence[4] = {27,'[','A','\0'};
  42.  
  43. /* add char to escape sequence list */
  44.  
  45. static void Add2List(char C)
  46. {if(ListCnt<SIZE-1) ListBuf[ListCnt++] = C;
  47. }
  48.  
  49. /* clear escape sequence list */
  50.  
  51. static void ClearList(void)
  52. {int i;
  53.  ListCnt = 0;
  54.  for(i=0;i<SIZE;i++) ListBuf[i] ='\0';
  55. }
  56.  
  57. /* is character a digit ? */
  58.  
  59. static int IsDigit(char c)
  60. {if((c>='0')&&(c<='9')) return TRUE;
  61.  else return FALSE;
  62. }
  63.  
  64. /* is character alphabetic ? */
  65.  
  66. static int IsAlpha(char c)
  67. {if((c>='a')&&(c<='z')) return TRUE;
  68.  if((c>='A')&&(c<='Z')) return TRUE;
  69.  return FALSE;
  70. }
  71.  
  72. /*
  73. ** returns numeric parameter, advancing
  74. ** list index to next non-numeric digit
  75. */
  76.  
  77. static int EatDigits(int *IndexPtr)
  78. {int  Value = 0;
  79.  char Char;
  80.  /* while characters in escape sequence list */
  81.  while(*IndexPtr < ListCnt)
  82.    {Char = ListBuf[*IndexPtr];
  83.     if(IsDigit(Char))
  84.       {Value = 10*Value + (Char - '0');
  85.        (*IndexPtr)++;
  86.       }
  87.     else break;
  88.    }
  89.  return Value;
  90. }
  91.  
  92. /*
  93. ** The Escape sequence buffer is ready to interpret when:
  94. **   1) Sequence starts with "ESC [" , and
  95. **   2) Sequence ends with a alphabetic character.
  96. */
  97.  
  98. static void Interpret(void)
  99. {int i;
  100.  int Index;  /* index into ListBuf[] */
  101.  int Value;  /* parameter value */
  102.  int Row;
  103.  int Col;
  104.  if(Debug)
  105.    {DisplayChar('[');
  106.     for(i=0;i<ListCnt;i++) DisplayChar(ListBuf[i]);
  107.     DisplayChar(']');
  108.    }
  109.  Row = PaintGetRow();
  110.  Col = PaintGetCol();
  111.  Index = 2;
  112.  switch(ListBuf[ListCnt-1])
  113.    {
  114.     case 'A':  /*** ESC [ * A ***/
  115.       Value = EatDigits(&Index);
  116.       if(Value==0) Value = 1;
  117.       if(Index==ListCnt-1)
  118.         {/* move up 1 row */
  119.          Row -= Value;
  120.          if(Row<0) Row = 0;
  121.          PaintSetRow(Row);
  122.          PaintSetCol(Col);
  123.         }
  124.       break;
  125.     case 'B':  /*** ESC [ * B ***/
  126.       Value = EatDigits(&Index);
  127.       if(Value==0) Value = 1;
  128.       if(Index==ListCnt-1)
  129.         {/* move down 1 row */
  130.          Row += Value;
  131.          if(Row>NROWS) Row = NROWS;
  132.          PaintSetRow(Row);
  133.         }
  134.       break;
  135.     case 'C':  /*** ESC [ * C ***/
  136.       Value = EatDigits(&Index);
  137.       if(Value==0) Value = 1;
  138.       if(Index==ListCnt-1)
  139.         {/* move right 1 column */
  140.          Col += Value;
  141.          if(Col>NCOLS) Col = NCOLS;
  142.          PaintSetCol(Col);
  143.         }
  144.       break;
  145.     case 'D':  /*** ESC [ * D ***/
  146.       Value = EatDigits(&Index);
  147.       if(Value==0) Value = 1;
  148.       if(Index==ListCnt-1)
  149.         {/* move left 1 column */
  150.          Col -= Value;
  151.          if(Col<0) Col = 0;
  152.          PaintSetCol(Col);
  153.         }
  154.       break;
  155.     case 'f':  /***  ESC [ * ; * f  ***/
  156.     case 'H':  /***  ESC [ * ; * H  ***/
  157.                /***  ESC [ = * H    ***/
  158.       if(ListBuf[2]=='=')
  159.          {Index++;
  160.           Value = EatDigits(&Index);
  161.           break;
  162.          }
  163.       Row = EatDigits(&Index) - 1;
  164.       if(ListBuf[Index]==';')
  165.         {Index++;
  166.          Col = EatDigits(&Index) - 1;
  167.         }
  168.       if(Index==ListCnt-1)
  169.         {PaintSetRow(Row);
  170.          PaintSetCol(Col);
  171.         }
  172.       break;
  173.     case 'J':  /***  ESC [ 2 J  ***/
  174.       if((ListBuf[2]=='2')&&(ListCnt==4))
  175.          {/* erase display */
  176.           PaintClearScreen();
  177.           break;
  178.          }
  179.       break;
  180.     case 'K': /***  ESC [ 2 K  ***/
  181.       if((ListBuf[2]=='2')&&(ListCnt==4))
  182.         {/* erase to EOL */
  183.          PaintClearEOL();
  184.         }
  185.       break;
  186.     case 'n': /***  ESC [ 6 n  ***/
  187.       if((ListBuf[2]=='6')&&(ListCnt==4))
  188.          {/* output Cursor Position ReportBuffer (CPR) */
  189.           Row = PaintGetRow();
  190.           Col = PaintGetCol();
  191.           /* save up position report */
  192.           wsprintf((LPSTR)ReportBuffer,"%c[%d;%dR",ESC,Row+1,Col+1);
  193.           ReportLeft = 0;
  194.           ReportRight = lstrlen((LPSTR)ReportBuffer) - 1;
  195.           break;
  196.          }
  197.       break;
  198.     case 'u':  /***  ESC [ u  ***/
  199.       if((ListBuf[2]=='u')&&(ListCnt==3))
  200.         {/* restore saved cursor position */
  201.          PaintSetRow(SavedRow);
  202.          PaintSetCol(SavedCol);
  203.         }
  204.       break;
  205.     case 's':  /***  ESC [ s  ***/
  206.       if((ListBuf[2]=='S')&&(ListCnt==3))
  207.         {/* save cursor position */
  208.          SavedRow = PaintGetRow();
  209.          SavedCol = PaintGetCol();
  210.         }
  211.       break;
  212.     default:
  213.       /* sequence not recognized or not supported */
  214.       break;
  215.    } /* end-switch */
  216.  ClearList();
  217. }
  218.  
  219. /**********************/
  220. /*                    */
  221. /*  PUBLIC functions  */
  222. /*                    */
  223. /**********************/
  224.  
  225. /* set/clear Debug flag */
  226.  
  227. void AnsiDebug(int Flag)
  228. {Debug = Flag;
  229. }
  230.  
  231. /* display character */
  232.  
  233. int AnsiPutc(char C)
  234. {/* initialized ? */
  235.  if(!Initialized)
  236.     {ClearList();
  237.      Initialized = 1;
  238.     }
  239.  /* process character C */
  240.  if(C==ESC)
  241.     {/* start new escape sequence */
  242.      ListCnt = 0;
  243.      Add2List(ESC);
  244.      return 0;
  245.     }
  246.  else
  247.     {/* escape sequence started ? */
  248.      if(ListCnt==0)
  249.         {DisplayChar(C);
  250.          return 1;
  251.         }
  252.      else
  253.         {/* add to escape sequence */
  254.          Add2List(C);
  255.          /* last char in ListBuf[] alphabetic ? */
  256.          if(IsAlpha(ListBuf[ListCnt-1]))
  257.            {/* ready to interpret */
  258.             if(ListBuf[1]=='[') Interpret();
  259.             else ListCnt = 0;
  260.            }
  261.          return 0;
  262.         }
  263.     }
  264. }
  265.  
  266. /* display (null terminated) string */
  267.  
  268. int AnsiPuts(LPSTR String)
  269. {int i;
  270.  int Len = lstrlen(String);
  271.  for(i=0;i<Len;i++) AnsiPutc(*String++);
  272.  return Len;
  273. }
  274.  
  275. /* (virtual) ANSI keyboard */
  276.  
  277. int AnsiGetc(void)
  278. {if(ReportLeft==ReportRight) return -1;
  279.  return ReportBuffer[ReportLeft++];
  280. }
  281.  
  282. void AnsiUp(int Port)
  283. {EscSequence[2] = 'A';
  284.  SioPuts(Port,(LPSTR)EscSequence,3);
  285. }
  286.  
  287. void AnsiDown(int Port)
  288. {EscSequence[2] = 'B';
  289.  SioPuts(Port,(LPSTR)EscSequence,3);
  290. }
  291.  
  292. void AnsiRight(int Port)
  293. {EscSequence[2] = 'C';
  294.  SioPuts(Port,(LPSTR)EscSequence,3);
  295. }
  296.  
  297. void AnsiLeft(int Port)
  298. {EscSequence[2] = 'D';
  299.  SioPuts(Port,(LPSTR)EscSequence,3);
  300. }